import { useCallback, useEffect, useRef, useState } from "react";
import { FC, ReactElement } from "react";
import styled from "styled-components";
import {
  getBlogs,
  BlogStatus,
  BlogList,
  DeleteBlogProps,
  deleteBlog,
  BlogType,
  Sort,
} from "../../../api/blogApi";
import MarkDown from "../../MD/MarkDown";
import Head from "./Head";
import { useHistory } from "react-router-dom";
import { NotificationSuccess } from "../../common/Notification";
import { Button } from "antd";
import { OptionalItem } from "../../MD/BlogTags";
import { EditOutlined, DeleteOutlined } from "@ant-design/icons";
import { FlexDiv } from "../../BUI";
import { BrowseIcon, ThumbsUpIcon } from "../../BUI/Icon";
import { Pagination } from "antd";

interface IProps {}

const initialBlogList = {
  counts: 0,
  blogs: [],
};

//获取函数参数的类型
type Find = Parameters<typeof getBlogs>;

const BlogManage: FC<IProps> = (): ReactElement => {
  const { push } = useHistory();
  const [blogStatus, setBlogStatus] = useState<BlogStatus>(
    (localStorage.getItem("blogStatus") as BlogStatus) || BlogStatus.ALL
  );
  const [blogType, setBlogType] = useState<BlogType | "">(
    (localStorage.getItem("blogType") || "") as BlogType | ""
  );
  const [blogList, setBlogList] = useState<BlogList>(initialBlogList);
  const [self, setSelf] = useState(false);
  const [sort, setSort] = useState<Sort>(
    JSON.parse(localStorage.getItem("sort") || `{ "createAt": -1 }`)
  );
  const [currentPage, setCurrentPage] = useState(1);

  const fetchBlogList = useCallback(
    (
      status: BlogStatus,
      self: boolean,
      blogType: BlogType | "",
      sort: Sort,
      currentPage: number
    ) => {
      const find: Find[number]["find"] = {};
      status !== BlogStatus.ALL && (find["status"] = status);
      blogType && (find["type"] = blogType);
      getBlogs({ sort, find, self, skip: (currentPage - 1) * 20 }).then(
        ({ data }) => {
          console.log("blogs", data);
          data && setBlogList(data);
        }
      );
    },
    []
  );

  useEffect(() => {
    fetchBlogList(blogStatus, self, blogType, sort, currentPage);
    localStorage.setItem("blogStatus", blogStatus);
    localStorage.setItem("blogType", blogType);
    localStorage.setItem("sort", JSON.stringify(sort));
  }, [blogStatus, fetchBlogList, self, blogType, sort, currentPage]);

  const toggleBlogStatus = useCallback(
    (status: BlogStatus) => () => {
      setBlogStatus(status);
    },
    []
  );

  const toggleBlogType = useCallback(
    (type: BlogType) => () => {
      setBlogType(prevType => (prevType === type ? "" : type));
    },
    []
  );

  const toggleSelf = useCallback(() => {
    setSelf(state => !state);
  }, []);

  const toggleSortField = useCallback(
    field => () => {
      setSort(sort => ({ [field]: Object.values(sort)[0] }));
    },
    []
  );

  const toggleSortValue = useCallback(
    (value: 1 | -1) => () => {
      setSort(sort => ({ [Object.keys(sort)[0]]: value }));
    },
    []
  );

  const handleEditBlog = useCallback(
    id => () => push(`/md?blog=${id}`),
    [push]
  );

  const handleDeleteBlog = useCallback(
    (params: DeleteBlogProps) => async () => {
      const { data } = await deleteBlog(params);
      if (data) {
        NotificationSuccess(data);
        setBlogList(({ counts, blogs }) => ({
          counts: counts - 1,
          blogs: blogs.filter(blog => blog._id !== params._id),
        }));
      }
    },
    []
  );

  return (
    <Container>
      <Head
        counts={blogList.counts}
        blogStatus={blogStatus}
        toggleBlogStatus={toggleBlogStatus}
        self={self}
        toggleSelf={toggleSelf}
        blogType={blogType}
        toggleBlogType={toggleBlogType}
        sort={sort}
        toggleSortField={toggleSortField}
        toggleSortValue={toggleSortValue}
      />
      {blogList.blogs.map(blog => (
        <BlogItem
          onEdit={handleEditBlog(blog._id)}
          onDelete={handleDeleteBlog({
            _id: blog._id,
            tags: blog.tags,
            blogOwner: blog.userId,
          })}
          key={blog._id}
          blog={blog}
        />
      ))}
      <Pagination
        onChange={setCurrentPage}
        defaultCurrent={currentPage}
        total={blogList.counts}
        style={{ display: "flex", justifyContent: "center" }}
        pageSize={20}
        hideOnSinglePage={true}
        showSizeChanger={false}
      />
    </Container>
  );
};

interface IBlogItem {
  blog: BlogList["blogs"][number];
  onEdit: () => void;
  onDelete: () => void;
}

const BlogItem: FC<IBlogItem> = ({ blog, onEdit, onDelete }) => {
  const [confirmDel, setConfirmDel] = useState(false);
  const [countDown, setCountDown] = useState(3);
  const interval = useRef<any>(0);

  const ConfirmDelete = useCallback(() => {
    confirmDel ? onDelete() : setConfirmDel(true);
  }, [confirmDel, onDelete]);

  useEffect(() => {
    confirmDel &&
      (interval.current = setInterval(() => {
        setCountDown(count => {
          if (count === 1) {
            setConfirmDel(false);
            return 3;
          }
          return count - 1;
        });
      }, 1000));
    return () => {
      clearInterval(interval.current);
    };
  }, [confirmDel]);

  return (
    <BlogItemWrap>
      <div>
        <BlogItemStatus blogStatus={blog.status} blogType={blog.type} />
        <h3>{blog.title}</h3>
        <span>
          创建时间:{new Date(blog.createAt).toLocaleString()} <br /> 更新时间:
          {new Date(blog.updateAt).toLocaleString()}
        </span>
      </div>
      <MarkDown content={blog.introduce} syncScroll={false} />
      <FlexDiv items='center' justify='space-between'>
        <TagsWrap>
          {blog.tags.map(tag => (
            <OptionalItem key={tag}>
              <span>{tag}</span>
            </OptionalItem>
          ))}
        </TagsWrap>
        <FlexDiv items='center' space='2px'>
          <OptionalItem>
            <BrowseIcon />
            <span>{blog.browseCount}</span>
          </OptionalItem>
          <OptionalItem>
            <ThumbsUpIcon />
            <span>{blog.thumbsUp}</span>
          </OptionalItem>
          <OptionalItem>
            <ThumbsUpIcon down />
            <span>{blog.thumbsDown}</span>
          </OptionalItem>
          <Button icon={<EditOutlined />} onClick={onEdit} type='dashed'>
            编辑
          </Button>
          <Button
            icon={<DeleteOutlined />}
            onClick={ConfirmDelete}
            type='primary'
            danger={confirmDel}
          >
            {confirmDel ? `确定删除 ${countDown}` : "删除"}
          </Button>
        </FlexDiv>
      </FlexDiv>
    </BlogItemWrap>
  );
};

const BlogStatusColor: { [key: string]: string } = {
  [BlogStatus.PUBLIC]: "#0ab6fa",
  [BlogStatus.DRAFT]: "#ccc",
  [BlogStatus.PRIVATE]: "#faa",
};

const BlogTypeColor: { [key: string]: string } = {
  [BlogType.ORIGINAL]: "#51f",
  [BlogType.REPRINT]: "#00f",
};

const TagsWrap = styled(FlexDiv)`
  & > div:first-child {
    margin-left: 0;
  }
`;

const BlogItemStatus = styled.div<{ blogStatus: BlogStatus; blogType: string }>`
  border-radius: 3px;
  font-size: 12px;
  display: flex;
  overflow: hidden;
  margin-right: 10px;
  color: #fff;

  &::before {
    content: "${props => props.blogType}";
    background: ${props => BlogTypeColor[props.blogType]};
    flex: 1;
    display: flex;
    align-items: center;
    padding: 2px 5px;
  }
  &::after {
    content: "${props => props.blogStatus}";
    background: ${props => BlogStatusColor[props.blogStatus]};
    flex: 1;
    display: flex;
    align-items: center;
    padding: 2px 5px;
  }
`;

const BlogItemWrap = styled.div`
  margin: 10px 5px;
  padding: 5px;
  box-shadow: 0 0 5px 0 #ccc;
  transition: all 0.2s linear;

  &:hover {
    transform: translateY(-1px);
    box-shadow: -1px 3px 20px 0px #b3b1b1;
  }

  & > div.markdown-body {
    max-height: 200px;
    overflow: hidden;
    padding: 5px 0;
  }

  & > div:first-child {
    display: flex;
    align-items: center;
    justify-content: space-between;

    h3 {
      margin: 0;
    }
    span {
      color: #666;
      font-size: 12px;
    }
  }
  & > section {
    max-height: 150px;
  }
`;

export default BlogManage;

const Container = styled.div`
  width: 100%;
  height: 100%;
  background: #fff;
  overflow-x: hidden;
  overflow-y: scroll;
  padding-bottom: 20px;
`;
